﻿using System;
using System.Linq;
using System.Web;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Xml;
using CookComputing.XmlRpc;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Modules.Forum;
using DotNetNuke.Common.Utilities;

namespace ACS.Modules.TapaTalk
{

    [XmlRpcService(Name = "TapaTalkService", Description = "This is XML-RPC Service which implement TapaTalk API for Dotnetnuke Forum.", UseIntTag = true, AutoDocumentation = true)]
    public class Service : XmlRpcService
    {
    #region "Private members"
        int _ForumModule = 0;
        int _TapatalkModule = 0;
        int _UserID = -1;
        TapatalkSettings _Settings;
        string _Protocol = "";
        string _Authority = "";
        string _AppPath = "";
    #endregion
 
    #region "Tapatalk Services: FORUM"
        [XmlRpcMethod("get_config")]
        public  XmlRpcStruct getConfig()
        {           
            GetDNNInfo();
            XmlRpcStruct rpcstruct = new XmlRpcStruct();
            //this.Context.Response.AddHeader("pepe", "hillo");          
  
            rpcstruct.Add("version", "dev");
            rpcstruct.Add("is_open", _Settings.Is_Open);
            rpcstruct.Add("guest_okay", _Settings.Guest_Access);
            rpcstruct.Add("reg_url", "../register.aspx");
            rpcstruct.Add("api_level", "3");
            rpcstruct.Add("disable_search", (_Settings.Disable_Search?"1":"0") );
            rpcstruct.Add("disable_latest", ( _Settings.Disable_Latest?"1":"0") );
            rpcstruct.Add("disable_pm", (_Settings.Disable_Pm?"1":"0"));
            //ejemplo de cómo obtener un valor cadena en base64
            //rpcstruct.Add("prueb", Common.StringToBytes("Mi cadena muy larga y preciosa!"));
            return rpcstruct;                    

        }
        [XmlRpcMethod("get_forum")]
        public ForumsStructRequest[] getForum()
        {
            GetDNNInfo();

            List<ForumsStructRequest> _Forums = new List<ForumsStructRequest>();

            GroupController cntGroup = new GroupController();
            List<GroupInfo> AuthorizedGroups = cntGroup.GroupGetAllAuthorized(_Settings.forumModuleID, _UserID, false, _Settings.forumTabID);
            int AuthForumsCount = 0;

            if (AuthorizedGroups.Count > 0)
            {
                foreach (GroupInfo objGroup in AuthorizedGroups)
                {

                    ForumsStructRequest _Forum = new ForumsStructRequest();

                    _Forum.forum_id = "C" + objGroup.GroupID.ToString();
                    _Forum.forum_name = Common.StringToBytes(objGroup.Name);
                    _Forum.parent_id = "0";
                    _Forum.sub_only = true;

                    List<ForumsStructRequest> _SubForums = new List<ForumsStructRequest>();

                    List<ForumInfo> arrAuthForums = new List<ForumInfo>();
                    arrAuthForums = cntGroup.AuthorizedForums(_UserID, objGroup.GroupID, false, _Settings.forumModuleID, _Settings.forumTabID);
                    if (arrAuthForums.Count > 0)
                    {
                        AuthForumsCount += arrAuthForums.Count;
                        foreach (ForumInfo F in arrAuthForums)
                        {
                            if (F.ParentID == 0)
                            {
                                ForumsStructRequest Forum = new ForumsStructRequest();

                                Forum.forum_id = F.ForumID.ToString();
                                Forum.forum_name = Common.StringToBytes(F.Name);
                                Forum.parent_id = "C" + objGroup.GroupID.ToString();
                                Forum.sub_only = false;
                                Forum.can_subscribe = true;
                                if (F.ContainsChildForums)
                                {
                                    List<ForumsStructRequest> _SubSubForums = new List<ForumsStructRequest>();
                                    CogerHijos(ref _SubSubForums, F);
                                    Forum.child = _SubSubForums.ToArray();

                                }
                                _SubForums.Add(Forum);
                            }

                        }

                    }

                    _Forum.child = _SubForums.ToArray();

                    _Forums.Add(_Forum);
                }
            }

            return _Forums.ToArray();

        }
 
        [XmlRpcMethod("mark_all_as_read")]       
        public XmlRpcStruct mark_all_as_read(string forum_id = null)
        {
            GetDNNInfo();
            XmlRpcStruct rpcstruct = new XmlRpcStruct();
            //a implementar, devuelve siempre true para pruebas        

            rpcstruct.Add("result", "1");
            rpcstruct.Add("result_text", Common.StringToBytes(""));

            return rpcstruct;
        }

        [XmlRpcMethod("login_forum")]
        public XmlRpcStruct login_forum(string forum_id,byte[] password)
        {
            GetDNNInfo();
            XmlRpcStruct rpcstruct = new XmlRpcStruct();
            //a implementar, devuelve siempre true para pruebas        

            rpcstruct.Add("result", true);
            rpcstruct.Add("result_text", Common.StringToBytes(""));

            return rpcstruct;
        }

        [XmlRpcMethod("get_board_stat")]
        public XmlRpcStruct get_board_stat()
        {
            GetDNNInfo();
            XmlRpcStruct rpcstruct = new XmlRpcStruct();
            //a implementar, devuelve siempre true para pruebas        

            rpcstruct.Add("total_threads", 1);
            rpcstruct.Add("total_posts", 1);
            rpcstruct.Add("total_members", 1);
            rpcstruct.Add("guest_online", 1);
            rpcstruct.Add("total_online", 1);
            rpcstruct.Add("active_members", 1); //opcional

            return rpcstruct;
        }

    #endregion

    #region "Tapatalk Services: USER"
        [XmlRpcMethod("login")]
        public XmlRpcStruct login(byte[] login_name, byte[] password)
        {
            GetDNNInfo();
            XmlRpcStruct rpcstruct = new XmlRpcStruct();
            //a implementar, devuelve siempre true para pruebas        

            rpcstruct.Add("result", true);
            rpcstruct.Add("result_text", Common.StringToBytes(""));
            return rpcstruct;
        }

        [XmlRpcMethod("get_inbox_stat")]
        public XmlRpcStruct get_inbox_stat()
        {
            GetDNNInfo();
            XmlRpcStruct rpcstruct = new XmlRpcStruct();
            //a implementar, devuelve siempre true para pruebas        

            rpcstruct.Add("inbox_unread_count", 0);
            rpcstruct.Add("subscribed_topic_unread_count", 0);
            return rpcstruct;
        }

        [XmlRpcMethod("logout_user")]
        public XmlRpcStruct logout_user()
        {
            GetDNNInfo();
            XmlRpcStruct rpcstruct = new XmlRpcStruct();
            //a implementar, devuelve siempre true para pruebas        
            rpcstruct.Add("result", true);
            rpcstruct.Add("result_text", Common.StringToBytes(""));
            return rpcstruct;
        }

        [XmlRpcMethod("get_online_users")]
        public XmlRpcStruct get_online_users()
        {
            GetDNNInfo();
            XmlRpcStruct rpcstruct = new XmlRpcStruct();
            //a implementar, devuelve siempre true para pruebas        
            rpcstruct.Add("member_count", 1);
            rpcstruct.Add("guest_count", 1);
            List<UsersOnLineStructRequest> _UsersOnLine = new List<UsersOnLineStructRequest>();
            UsersOnLineStructRequest User1 = new UsersOnLineStructRequest();
            User1.display_name=Common.StringToBytes("Espinazo");
            User1.display_text=Common.StringToBytes("En Línea");
            _UsersOnLine.Add(User1);
            rpcstruct.Add("list",_UsersOnLine.ToArray());
            return rpcstruct;
        }

        [XmlRpcMethod("get_user_info")]
        public XmlRpcStruct get_user_info(byte[] user_name)
        {
            GetDNNInfo();
            XmlRpcStruct rpcstruct = new XmlRpcStruct();
            //a implementar, devuelve siempre true para pruebas        
            rpcstruct.Add("post_count", 2);
            rpcstruct.Add("reg_time", DateTime.Now);
            rpcstruct.Add("last_activity_time", DateTime.Now);
            rpcstruct.Add("icon_url", ""); //obtener el avatar del usuario
            rpcstruct.Add("display_name", Common.StringToBytes("Espinazo"));
            rpcstruct.Add("display_text", Common.StringToBytes("hola radiola"));
            rpcstruct.Add("is_online",true);
            rpcstruct.Add("accept_pm", true);

            return rpcstruct;
        }

        [XmlRpcMethod("get_user_topic")]
        public GetUserTopicsStructRequest[] get_user_topic(byte[] user_name)
        {
            GetDNNInfo();
            //a implementar, devuelve siempre true para pruebas        
 
            List<GetUserTopicsStructRequest> _Topics = new List<GetUserTopicsStructRequest>();
            GetUserTopicsStructRequest UnTopic = new GetUserTopicsStructRequest();
            UnTopic.forum_id="1";
            UnTopic.forum_name=Common.StringToBytes("PropertyMap");
            UnTopic.topic_id="1";
            UnTopic.topic_title =Common.StringToBytes("Título del topic");
            UnTopic.last_reply_author_name=Common.StringToBytes("Perico Palotes");
            UnTopic.last_reply_author_display_name=Common.StringToBytes("El Palotes");
            UnTopic.short_content=Common.StringToBytes("Primero 200 caracteres del topic");
            UnTopic.icon_url =""; //avatar del usuario
            UnTopic.last_reply_time = DateTime.Now;
            UnTopic.reply_number= 1;
            UnTopic.view_number = 10;
            UnTopic.new_post= false;
            _Topics.Add(UnTopic);
            return _Topics.ToArray();
            //return rpcstruct;
        }
        [XmlRpcMethod("get_user_reply_post")]
        public GetUserReplyPostStructRequest[] get_user_reply_post(byte[] user_name, string user_id)
        {
            GetDNNInfo();
            //a implementar, devuelve siempre true para pruebas   
            List<GetUserReplyPostStructRequest> _Topics = new List<GetUserReplyPostStructRequest>();
            GetUserReplyPostStructRequest UnTopic = new GetUserReplyPostStructRequest();
            UnTopic.forum_id = "1";
            UnTopic.forum_name = Common.StringToBytes("PropertyMap");
            UnTopic.topic_id = "1";
            UnTopic.topic_title = Common.StringToBytes("Título del topic");
            UnTopic.icon_url = ""; //avatar del usuario
            UnTopic.post_id = "1";
            UnTopic.post_time = DateTime.Now;          
            UnTopic.reply_number = 1;
            UnTopic.new_post=false;
            UnTopic.view_number = 1;
            UnTopic.short_content = Common.StringToBytes("primeros 200 caracters del topic");
            _Topics.Add(UnTopic);
            return _Topics.ToArray();
        }
        #endregion

    #region "Topic"
        [XmlRpcMethod("new_topic")]
        public XmlRpcStruct new_topic(string forum_id,byte[] subject,byte[] text_body)
        {
            GetDNNInfo();
            XmlRpcStruct rpcstruct = new XmlRpcStruct();
            //a implementar, devuelve siempre true para pruebas        
            rpcstruct.Add("result",true);
            rpcstruct.Add("result_text", Common.StringToBytes(""));
            rpcstruct.Add("topic_id", "222");
            //si necesita moderación enviar esta clave
            rpcstruct.Add("state", "1");
           
            return rpcstruct;      
        }
        [XmlRpcMethod("get_topic")]
        public XmlRpcStruct get_topic(string forum_id, int start_num,int last_num, string mode)
        {
            GetDNNInfo();
            XmlRpcStruct rpcstruct = new XmlRpcStruct();
            //a implementar, devuelve siempre true para pruebas        
            rpcstruct.Add("total_topic_num", 1);
            rpcstruct.Add("forum_id", "1");
            rpcstruct.Add("forum_name", Common.StringToBytes("Nombre del Foro"));
            rpcstruct.Add("can_post", true);
            rpcstruct.Add("prefix_id", "1");
            rpcstruct.Add("")

            rpcstruct.Add("state", "1");

            return rpcstruct;
        }
    #endregion

    #region "Private Methods"
        private void CogerHijos(ref List<ForumsStructRequest> _SubForums, ForumInfo F)
        {

            List<ForumInfo> arrForums = default(List<ForumInfo>);
            arrForums = CBO.FillCollection<ForumInfo>(DotNetNuke.Modules.Forum.DataProvider.Instance().ForumGetAllByParentID(F.ForumID, F.GroupID, true));

            foreach (ForumInfo _F in arrForums)
            {

                ForumsStructRequest Forum = new ForumsStructRequest();

                Forum.forum_id = _F.ForumID.ToString();
                Forum.forum_name = Common.StringToBytes(_F.Name);
                Forum.parent_id = _F.ParentID.ToString();
                Forum.sub_only = false;
                Forum.can_subscribe = true;
                if (_F.ContainsChildForums)
                {
                    List<ForumsStructRequest> _SubSubForums = new List<ForumsStructRequest>();
                    CogerHijos(ref _SubSubForums, _F);
                    Forum.child = _SubSubForums.ToArray();

                }
                _SubForums.Add(Forum);

            }
        }
        private void GetDNNInfo(){
            this._Protocol = this.Context.Request.Url.Scheme;
            this._Authority = this.Context.Request.Url.Authority;
            this._AppPath = this.Context.Request.ApplicationPath;
            string TapatalkModule = (this.Context.Request.Url.Segments[this.Context.Request.Url.Segments.Count() - 3]).Replace("/", "");
            string ForumModule = (this.Context.Request.Url.Segments[this.Context.Request.Url.Segments.Count() - 2]).Replace("/","");
            if ((Common.IsNumeric(ForumModule)) && (Common.IsNumeric(TapatalkModule)))
            {
                _TapatalkModule = Convert.ToInt32(TapatalkModule);
                _ForumModule = Convert.ToInt32(ForumModule);
                
               
                _Settings = TapatalkSettings.GetTapatalkSettings(_TapatalkModule);

                //cookie de usuario
                //string strCookie = ("_Module" + (_Settings.AllSettings["PortalID"].ToString() + "_" + _Settings.forumModuleID.ToString() + "_FastLogin"));
                //  Store the cookie 
                //HttpCookie objCookie = new HttpCookie(strCookie);
                //objCookie.Value = "anonymous";
                //objCookie.Expires = DateTime.MaxValue;
                //  never expires
               // this.Context.Response.SetCookie(objCookie);
 
            }
            else
            {
                throw new XmlRpcFaultException(100, "Invalid argument"); 
            }
}

    #endregion

    #region "Estructuras"
        [XmlRpcMissingMapping(MappingAction.Ignore)]
        public struct ForumsStructRequest
        {
            public string forum_id;
            public byte[] forum_name;
            public byte[] description;
            public string parent_id;
            public string logo_url;
            public bool new_post;
            public int unread_count;
            public bool is_protected;
            public string url;
            public bool sub_only;
            public bool can_subscribe;
            public bool is_suscribed;
            public ForumsStructRequest[] child;

        }
        [XmlRpcMissingMapping(MappingAction.Ignore)]
        public struct UsersOnLineStructRequest
        {
            public byte[] user_name;
            public byte[] display_name;
            public byte[] display_text;
            public string icon_url;
        }
        public struct GetUserTopicsStructRequest
        {
            public string forum_id;
            public byte[] forum_name;
            public string topic_id;
            public byte[] topic_title;
            public byte[] last_reply_author_name;
            public byte[] last_reply_author_display_name;
            public byte[] short_content; // 1) Remove all BBCode except [ur], [img]. 2) Convert "[url http://...]http://…..[/url]" to "[url]". 3) Convert "[img]http://…..[/img]" to "[img]". 4) Remove "Last edited by..." tag at the end. 5) Remove all non-displayable characters (e.g. \n, \t, etc). 6) Remove all whitespace, /n and /r at the begining and ending of the content. 7) return only first 200 characters
            public string icon_url;
            public DateTime last_reply_time;
            public int reply_number;
            public int view_number;
            public Boolean new_post;

        }
        public struct GetUserReplyPostStructRequest
        {
            public string forum_id;
            public byte[] forum_name;
            public string topic_id;
            public byte[] topic_title;
            public string icon_url;
            public string post_id;
            public DateTime post_time;
            public int reply_number;
            public Boolean new_post;
            public int view_number;
            public byte[] short_content; //solo primeros 200 caracteres
        }
    #endregion


    }


}